package com.authine.cloudpivot.ext.controller;

import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.engine.api.facade.FileStoreFacade;
import com.authine.cloudpivot.engine.api.model.bizmodel.BizPropertyModel;
import com.authine.cloudpivot.engine.api.model.bizmodel.BizSchemaModel;
import com.authine.cloudpivot.engine.api.model.runtime.AttachmentModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectQueryModel;
import com.authine.cloudpivot.engine.api.model.runtime.SelectionValue;
import com.authine.cloudpivot.engine.component.query.api.FilterExpression;
import com.authine.cloudpivot.engine.component.query.api.Page;
import com.authine.cloudpivot.engine.component.query.api.helper.PageableImpl;
import com.authine.cloudpivot.engine.component.query.api.helper.Q;
import com.authine.cloudpivot.engine.enums.status.SequenceStatus;
import com.authine.cloudpivot.engine.enums.type.BizPropertyType;
import com.authine.cloudpivot.engine.enums.type.DefaultPropertyType;
import com.authine.cloudpivot.ext.utils.CourseCoverWatermarkUtils;
import com.authine.cloudpivot.ext.utils.ExcelUtils;
import com.authine.cloudpivot.ext.utils.SchemaUtils;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.api.view.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author hxd
 * @Date 2022/3/7 11:53
 * @Description
 **/
@Slf4j
@RestController
@RequestMapping("/api/publish")
public class CoursePublishController extends BaseController {


    @Autowired
    Redisson redisson;

    @Autowired
    FileStoreFacade fileStoreFacade;
    @Autowired
    private RedisTemplate<String, AttachmentModel> redisTemplate;


    /**
     *  生成课程编码
     *
     *   //课程分类代码+课程系列代码+课程类别代码+年份+三位流水号+课程等级代码。
     * @param
     * @return
     */

    @PostMapping("generateKcSequenceNo")
    private ResponseResult generateKcSequenceNo(@RequestBody List<String> bizIdList){

        if (CollectionUtils.isEmpty(bizIdList)) {
            return getErrResponseResult(-1L,"参数不能为空");
        }

        List<String> failList = new ArrayList<>();

       bizIdList.forEach(bizId-> {
           try {
               ResponseResult responseResult = generateCode(bizId);
               if (responseResult.getErrcode() != 0) {
                   failList.add(responseResult.getErrmsg());
               }
           } catch (RuntimeException e) {

               failList.add(e.getMessage());
           } catch (Exception e) {
               failList.add(StrUtil.format("系统处理异常:{}",bizId));
           }
       });

       if (CollectionUtils.isEmpty(failList)){
           return getOkResponseResult("全部成功");
       }else if(bizIdList.size()==failList.size()) {
           return getErrResponseResult(-1L,StrUtil.format("全部失败:{}", JSON.toJSONString(failList)));
       }else {
           return getErrResponseResult(-1L,StrUtil.format("部分失败:{}", JSON.toJSONString(failList)));
       }

    }


    private ResponseResult generateCode(String bizId){

        log.info("\n===========进入生成课程编码方法,bizId={}",bizId);

        BizObjectCreatedModel kcsbNew = getBizObjectFacade().getBizObject("kcsbNew", bizId);

        if (kcsbNew ==null){
            log.info("\n===========生成课程编码失败,数据不存在,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,数据不存在,bizId={}",bizId));
        }
        String kcbh = kcsbNew.getString("kcbh");
        if (!StringUtils.isEmpty(kcbh)){
            log.info("\n===========生成课程编码失败,编号已存在,kcbh={},bizId={}",kcbh,bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,编号已存在,kcbh={},bizId={}",kcbh,bizId));
        }
        //课程分类代码(课程分类删掉了用活动类别)
        String modality = kcsbNew.getString("hdlb");
        if (StringUtils.isEmpty(modality)){
            log.info("\n===========生成课程编码失败,课程分类(活动类别)为空,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,课程分类(活动类别)为空,bizId={}",bizId));
        }
        modality =getCode("kcflbm","kcflbm","kcflmc",modality,"kcfldm");

        //课程系列代码
        String series = kcsbNew.getString("series");
        if (StringUtils.isEmpty(series)){
            log.info("\n===========生成课程编码失败,课程系列为空,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,课程系列为空,bizId={}",bizId));
        }
        series = getCode("kcxlbm","kcxlbm","kcxlmc",series,"kcxlbm");

        //课程类别代码
        String category = kcsbNew.getString("category");
        if (StringUtils.isEmpty(category)){
            log.info("\n===========生成课程编码失败,课程类别为空,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,课程类别为空,bizId={}",bizId));
        }
        category = getCode("kclbbm","kclbbm","kclbmc",category,"kclbdm");
        //课程等级代码
        String kcdj = kcsbNew.getString("kcdj");
        if (StringUtils.isEmpty(kcdj)){
            log.info("\n===========生成课程编码失败,课程等级为空,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,课程等级为空,bizId={}",bizId));
        }
        kcdj = getCode("kcdj","kcdj","kcdj",kcdj,"kcdjdm");
        String yearStr = kcsbNew.getString("psnd");
        if (yearStr==null){
            log.info("\n===========生成课程编码失败,课程年度不能为空,bizId={}",bizId);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编码失败,课程年度不能为空,bizId={}",bizId));
        }

        //课程分类代码+课程系列代码+课程类别代码+年份+三位流水号+课程等级代码。
        String codeTemp = modality.concat(series).concat(category).concat(yearStr).concat("{}").concat(kcdj);

        boolean isLock =false;
        String courseCode = null;
        RLock lock = redisson.getLock(codeTemp);

        try {
            isLock = lock.tryLock(3, TimeUnit.SECONDS);
            if (isLock){

                //查询编码序号
                BizObjectQueryModel  queryModel = new BizObjectQueryModel();
                queryModel.setSchemaCode("courseCodeSerialNumber");
                queryModel.setQueryCode("courseCodeSerialNumber");

                queryModel.setPageable(new PageableImpl(0,20));

                queryModel.setFilterExpr(Q.it("code", FilterExpression.Op.Eq, codeTemp));

                Page<BizObjectModel> page = getBizObjectFacade().queryBizObjects(queryModel);

                //保存编码序号
                BizObjectModel bizObjectModel;
                int serialNo ;
                if (page.getTotal()==0){
                    log.info("==========================新增编码序号");
                    bizObjectModel = new BizObjectCreatedModel("courseCodeSerialNumber",new HashMap<String,Object>(),false);
                    bizObjectModel.put("code",codeTemp);
                }else {
                    log.info("==========================修改编码序号");
                    bizObjectModel = page.getContent().get(0);
                }

                serialNo = MapUtils.getInteger(bizObjectModel.getData(),"serialNo",0);
                bizObjectModel.put("serialNo",++serialNo);
                //保存
                getBizObjectFacade().saveBizObject(getUserId(),bizObjectModel,false);
                int serialSize = 3;
                //序号补0
                String serialNoStr = String.format("%0"+serialSize+"d",serialNo);


                courseCode = StrUtil.format(codeTemp,serialNoStr);

                log.info("\n==============获取到课程编号:{}",courseCode);
            }

        }catch (Exception e){
            log.info("======================生成课程编号失败,系统异常:{}",e);
            return getErrResponseResult(-1l,StrUtil.format("生成课程编号失败,系统异常,bizId={}",bizId));
        }finally {
            if (isLock){
                lock.unlock();
            }
        }

        if (courseCode != null){
            kcsbNew.put("kcbh",courseCode);
            getBizObjectFacade().saveBizObject(kcsbNew.getCreater().getId(),kcsbNew,false);
        }

        return getOkResponseResult("成功");
    }




    private String getCode (String schemaCode,String queryCode,String propertyCode,String value,String code){
        //查询对应代码
        BizObjectQueryModel queryModel = new BizObjectQueryModel();
        queryModel.setSchemaCode(schemaCode);
        queryModel.setQueryCode(queryCode);

        queryModel.setPageable(new PageableImpl(0,20));
        FilterExpression.Item it = Q.it(propertyCode, FilterExpression.Op.Eq, value);

        queryModel.setFilterExpr(it);

        Page<BizObjectModel> page = getBizObjectFacade().queryBizObjects(queryModel);

        if (page.getTotal()==0){
            log.info("模型schemaCode={},数据项propertyCode={},值={}的数据不存在",schemaCode,propertyCode,value);
            throw new RuntimeException(StrUtil.format("模型schemaCode={},数据项propertyCode={},值={}的数据不存在",schemaCode,propertyCode,value));
        }

        BizObjectModel ruleModel = page.getContent().get(0);

        String codeValue = ruleModel.getString(code);


        if (StringUtils.isEmpty(codeValue)){
            log.info("模型schemaCode={},数据项propertyCode={}的值不能为空",schemaCode,code);
            throw new RuntimeException(StrUtil.format("模型schemaCode={},数据项propertyCode={}的值不能为空",schemaCode,code));
        }

        return codeValue;
    }

    /**
     * 进入发布入库方法
     * @param
     */
    @PostMapping("pushStory")
    public ResponseResult pushStory(@RequestBody List<String> bizIdList){

        if (CollectionUtils.isEmpty(bizIdList)) {
            return getErrResponseResult(-1L,"参数不能为空");
        }

        List<String> failList = new ArrayList<>();

        bizIdList.forEach(bizId-> {
            try {
                ResponseResult responseResult = coursePublish(bizId);
                if (responseResult.getErrcode() != 0) {
                    failList.add(responseResult.getErrmsg());
                }
            } catch (RuntimeException e) {

                failList.add(e.getMessage());
            } catch (Exception e) {
                failList.add(StrUtil.format("系统处理异常:{}",bizId));
            }
        });

        if (CollectionUtils.isEmpty(failList)){
            return getOkResponseResult("全部成功");
        }else if(bizIdList.size()==failList.size()) {
            return getErrResponseResult(-1L,StrUtil.format("发布全部失败:{}", JSON.toJSONString(failList)));
        }else {
            return getErrResponseResult(-1L,StrUtil.format("发布部分失败:{}", JSON.toJSONString(failList)));
        }


    }

    private ResponseResult coursePublish(String bizId){

        log.info("\n===========进入发布入库方法,bizId={}",bizId);
        ResponseResult.ResponseResultBuilder<Object> resp = ResponseResult.builder().errcode(-1l);

        //获取课程申报数据
        BizObjectCreatedModel kcsbNew = getBizObjectFacade().getBizObject("kcsbNew", bizId);

        if (kcsbNew == null) {
            return  resp.errmsg("课程申报数据不存在").build();
        }

        String kcbh = kcsbNew.getString("kcbh");
        if (StringUtils.isEmpty(kcbh)) {
            return resp.errmsg(StrUtil.format("课程编号不能为空:课程Id={}",bizId)).build();
        }

        //判断入库数据是否存在
        BizObjectQueryModel query = new BizObjectQueryModel();
        query.setSchemaCode("kcqd");
        query.setQueryCode("kcqd");
        query.setPageable(new PageableImpl(0,10));
        query.setFilterExpr(Q.it("kcbh", FilterExpression.Op.Eq, kcbh));

        Page<BizObjectModel> page = getBizObjectFacade().queryBizObjects(query);
        if (page.getTotal() > 0||page.getContent().size()>0) {
            return resp.errmsg(StrUtil.format("课程已入库,课程编号:{}",kcbh)).build();
        }

        //组合入库数据
        BizSchemaModel bizSchemaModel = this.getAppManagementFacade().getBizSchemaBySchemaCode("kcqd", true);

        //获取数据项code , 不是子表,已发布,不是默认字段
        List<String> fieldList = bizSchemaModel.getProperties().stream()
                .filter(prop -> !prop.getDefaultProperty() && prop.getPropertyType() != BizPropertyType.CHILD_TABLE && prop.getPublished())
                .map(BizPropertyModel::getCode).collect(Collectors.toList());

        //创建入库普通数据
        Map<String, Object> data = new HashMap<>();
        fieldList.forEach(f-> data.put(f,kcsbNew.get(f)));


        data.put("sbr",kcsbNew.get("creater"));
        data.put("sbsj",kcsbNew.getCreatedTime());
        data.put("kczt","已启用");
        data.put("dzs",0);
        data.put("xxrc",0);
        data.put("drsfxr",false);
        data.put("sfydz",false);
        data.put("year",kcsbNew.get("psnd"));
        data.put("modality",kcsbNew.get("hdlb"));
        data.put("previewArea",kcsbNew.get("DropdownArea"));
        data.put("kkffw",kcsbNew.get("StaffDeptMix"));
        data.put("psjb",kcsbNew.get("kcdj"));



        SelectionValue kczkfr = kcsbNew.getSelectionObject("kczkfr");
        if (kczkfr != null) {
            data.put("kczkfrtxt",kczkfr.getName());
        }


        //创建子表数据,课程结构kcqdCourseStructures,判断题kcqdJudgmentQuestion,选择题kcqdChoiceQuestion

        List<String> subDefaultCodeList =  new ArrayList<>(Arrays.asList("id","parentId","modifier","modifiedTime"));
        //课程结构 kcqdCourseStructures
        List<Map<String,Object>> courseStructuresList = (List<Map<String, Object>>) kcsbNew.getObject("courseStructuresNew");
        if (CollectionUtils.isNotEmpty(courseStructuresList)) {

            courseStructuresList.stream().forEach(map -> {
                //每条子表数据里把默认字段删掉
                subDefaultCodeList.forEach(k-> map.remove(k));
            });
            data.put("kcqdCourseStructures",courseStructuresList);
        }


        //图文--课程结构
        List<Map<String, Object>> alCourseStructuresList = (List<Map<String, Object>>) kcsbNew.getObject("alkcjg");
        if (CollectionUtils.isNotEmpty(alCourseStructuresList)) {

            courseStructuresList.stream().forEach(map -> {
                //每条子表数据里把默认字段删掉
                subDefaultCodeList.forEach(k -> map.remove(k));
            });
            data.put("kcqdalkcjg", alCourseStructuresList);
        }

//        判断题 kcqdJudgmentQuestion
        List<Map<String,Object>> judgmentQuestionList = (List<Map<String, Object>>) kcsbNew.getObject("judgmentQuestionNew");
        if (CollectionUtils.isNotEmpty(judgmentQuestionList)) {

            judgmentQuestionList.stream().forEach(map -> {
                //每条子表数据里把默认字段删掉
                subDefaultCodeList.forEach(k-> map.remove(k));
            });
            data.put("kcqdJudgmentQuestion",judgmentQuestionList);
        }

//        选择题 kcqdChoiceQuestion
        List<Map<String,Object>> choiceQuestionList = (List<Map<String, Object>>) kcsbNew.getObject("choiceQuestionNew");
        if (CollectionUtils.isNotEmpty(choiceQuestionList)) {

            choiceQuestionList.stream().forEach(map -> {
                //每条子表数据里把默认字段删掉
                subDefaultCodeList.forEach(k-> map.remove(k));
            });
            data.put("kcqdChoiceQuestion",choiceQuestionList);
        }

        BizObjectCreatedModel bizModel = new BizObjectCreatedModel("kcqd", data, false);
        bizModel.setName(kcsbNew.getString("courseName"));
        bizModel.setSequenceStatus(SequenceStatus.COMPLETED.name());
        String rkId = getBizObjectFacade().saveBizObject(kczkfr.getId(), bizModel, false);

        log.info("创建入库表单数据成功,返回id={}",rkId);


        if (rkId != null) {
            //修改课程申报状态 已入库, 申报进度

            Map<String, Object> sbjd = new HashMap<>();
            sbjd.put("sbjdt",4);
            sbjd.put("ShortTextDQYW","已入库");
            BizObjectCreatedModel sbjdBiz  = new BizObjectCreatedModel("kcsbNew", sbjd, false);
            sbjdBiz.setId(bizId);
            getBizObjectFacade().saveBizObject(getUserId(),sbjdBiz,false);
        }


        return resp.errcode(0l).errmsg("入库成功").build();

    }

    /**
     *  通过导入批量修改课程申报
     */
    @PostMapping("/batchUpdateCourseDeclare")
    public ResponseResult batchUpdateCourseDeclare(MultipartFile file) throws Exception {

        String fileName = file.getName();
        //课程id,课程名称，课程系列，课程类别，课程属性
        List<String> colCode = new ArrayList<>(Arrays.asList("id","courseName","series","category","kcxl"));

        List<Map<String, Object>> kcList = ExcelUtils.excelParse(file.getInputStream(), fileName, colCode);


        String schemaCode = SchemaUtils.courseApply;

        //判断课程存在
        List<String> collect = kcList.stream().filter(m -> {
            boolean exists = getBizObjectFacade().existsBizObject(schemaCode, MapUtils.getString(m, DefaultPropertyType.ID.getCode(), ""));
            return !exists;
        }).map(m -> MapUtils.getString(m, "id", "")).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(collect)) {
            return getErrResponseResult(-1l,StrUtil.format("导入失败:课程id:{} ,不存在课程数据", org.apache.commons.lang3.StringUtils.join(collect,",")));
        }

        //修改课程表
        List<BizObjectModel> kcsbList = kcList.stream()
                .map(m -> new BizObjectCreatedModel(schemaCode, m, false)).collect(Collectors.toList());

        getBizObjectFacade().batchSaveBizObjectModel(getUserId(),kcsbList, DefaultPropertyType.ID.getCode());

        return getOkResponseResult("成功");
    }


    /**
     * 批量导入评审组
     *  包含业务(基层评审推荐，中心初评，中心终评)
     */
    @PostMapping("/batchImportReviewTeam")
    public ResponseResult batchImportReviewTeam(MultipartFile file,String type) throws Exception {


        if (StringUtils.isEmpty(type)) {
            return getErrResponseResult(-1l,"业务类型 type 不能为空");
        }

        if (!ArrayUtils.contains(new Object[]{"jcpstj","lrcpgl","zpgl"},type)){
            return getErrResponseResult(-1l,"业务类型 type 不是 基层评审推荐 或 中心初评 或 中心终评");
        }


        String fileName = file.getName();

        // 课程id,课程名称,评审组id,评审组织名称,评分标准id,评分标准名称
        List<String> colCode = new ArrayList<>(Arrays.asList("kcid","courseName","psz","pszName","pfbz","pfbzName"));

        List<Map<String, Object>> list = ExcelUtils.excelParse(file.getInputStream(), fileName, colCode);

        //判断课程
        List<String> collect = list.stream().map(m -> {
            String kcId = MapUtils.getString(m, "kcid", "");
            String courseName = String.valueOf(m.get("courseName")) ;

            BizObjectCreatedModel course = getBizObjectFacade().getBizObject(SchemaUtils.courseApply, kcId);
            if (course == null || StringUtils.isEmpty(course.getId())) {
                return StrUtil.format("课程id:{},课程名称:{},课程数据不存在", kcId, courseName);
            }
            String shortTextDQYW = course.getString("ShortTextDQYW");
            if (!type.equals(shortTextDQYW)) {
                return StrUtil.format("课程id:{},课程名称:{}, 业务类型不匹配,当前业务类型={}",kcId,courseName, shortTextDQYW);
            }
            //判断评审组是否存在
            String psz = MapUtils.getString(m, "psz", "");
            boolean isExists = getBizObjectFacade().existsBizObject(SchemaUtils.reviewTeam, psz);

            if (!isExists){
                return StrUtil.format("评审组id:{},评审组名称:{} 数据不存在",psz, String.valueOf(m.get("pszName")));
            }

            //判断评分标准是否存在
            String pfbz = MapUtils.getString(m, "pfbz", "");
            isExists = getBizObjectFacade().existsBizObject(SchemaUtils.scoringCriteria,pfbz);
            if (!isExists){
                return StrUtil.format("评分标准id:{},评分标准名称:{} 数据不存在",pfbz, String.valueOf(m.get("pfbzName")));
            }

            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(collect)) {
            return getErrResponseResult(-1l,StrUtil.format("导入失败==> {}", org.apache.commons.lang3.StringUtils.join(collect,",")));
        }


        //psz  基层评审组     pfb  基层评分表(评分标准)
        //cppsz 初评评审组    cppfbz  初评评分表(评分标准)
        //zppsz 终评评审组    zppfbz   终评评分表(评分标准)


        String pszCode ;
        String pfbCode ;

        if("jcpstj".equals(type)){
             pszCode = "psz";
             pfbCode = "pfb";
        }else if("lrcpgl".equals(type)){
             pszCode = "cppsz";
             pfbCode = "cppfbz";
        }else {
             pszCode = "zppsz";
             pfbCode = "zppfbz";
        }


        list.forEach(m->{
            Map<String, Object> modelMap = MapBuilder.create(new HashMap<String, Object>())
                    .put("kcid", m.get("kcid"))
                    .put("psz", m.get("psz"))
                    .put("pfbz", m.get("pfbz"))
                    .put("dqyw",type)
                    .build();
            //创建分配评审组
            BizObjectCreatedModel model = new BizObjectCreatedModel(SchemaUtils.matchReviewTeam, modelMap, false);
            getBizObjectFacade().saveBizObject(getUserId(), model, false);

            //修改课程申报
            modelMap = MapBuilder.create(new HashMap<String,Object>())
                    .put(pszCode,m.get("psz"))
                    .put(pfbCode,m.get("pfbz"))
                    .put("id", m.get("kcid"))
                    .build();
            model = new BizObjectCreatedModel(SchemaUtils.courseApply, modelMap, false);

            getBizObjectFacade().saveBizObject(getUserId(), model, false);
        });

        return getOkResponseResult("成功");
    }



    public static final String KEY_WORKFLOW_ATTACHMENT = "cloudpivot:fileupload:workflow_attachment";
    /**
     * 封面加水印
     */
    @PostMapping("courseCoverImagesWater")
    public ResponseResult courseCoverImagesWater(@RequestBody Map<String,Object> map)  {

        if (MapUtils.isEmpty(map)) {
            return getErrResponseResult(-1l, "参数不能为空");
        }

        Map<String, Object> fm = (Map<String, Object>) MapUtils.getMap(map, "fm");

        AttachmentModel attachment = JSON.parseObject(JSON.toJSONString(fm), AttachmentModel.class);

        String refId = MapUtils.getString(fm,"refId");
        String courseName = MapUtils.getString(map,"courseName");
        Double left = MapUtils.getDouble(map, "left");
        Double top = MapUtils.getDouble(map, "top");
        Integer size = MapUtils.getInteger(map, "size");
        String color = MapUtils.getString(map, "color");

        if (StringUtils.isEmpty(refId)) {
            return getErrResponseResult(-1l, "refId不能为空");
        }
        if (StringUtils.isEmpty(courseName)) {
            return getErrResponseResult(-1l, "课程名称不能为空");
        }

        if (StringUtils.isEmpty(color)) {
            return getErrResponseResult(-1l, "水印颜色不能为空");
        }
        if (left ==null || left.doubleValue()>=1 || left.doubleValue()<=0 ) {
            return getErrResponseResult(-1l, StrUtil.format("文字定位横坐标比不在区间(0,1)中,当前值={}",left));
        }
        if (top ==null || top.doubleValue()>=1 || top.doubleValue()<=0) {
            return getErrResponseResult(-1l, StrUtil.format("文字定位纵坐标比不在区间(0,1)中,当前值={}",top));
        }
        if (size ==null || size.intValue()>50 || size.intValue() <=10) {
            return getErrResponseResult(-1l,StrUtil.format("文字大小不在区间(10,50)中,当前值={}",size));
        }




        String fileName = attachment.getRefId().concat(attachment.getName());


        ByteArrayInputStream bais=null;

        InputStream inputStream= null;
        try {
            inputStream = fileStoreFacade.downloadFile(fileName);
            if (inputStream==null){
                return getErrResponseResult(-1l, String.format("文件[%s]不存在", fileName));
            }

            byte[] bytes = CourseCoverWatermarkUtils.drawCourseInfoImg(inputStream, courseName,color,left,top,size);

            int length = bytes.length;

            bais = new ByteArrayInputStream(bytes);

            String upRefId = UUID.randomUUID().toString().replaceAll("-","");
            String upFileName = upRefId.concat(attachment.getName());

            fileStoreFacade.fileUpload(upFileName, bais);
            String suffix = attachment.getName().substring(attachment.getName().lastIndexOf('.') + 1);
            AttachmentModel resourceModel = new AttachmentModel();
            resourceModel.setRefId(upRefId);
            resourceModel.setName(attachment.getName());
            resourceModel.setFileExtension(".".concat(suffix));
            resourceModel.setFileSize(length);
            resourceModel.setMimeType("image/".concat(attachment.getName().substring(attachment.getName().lastIndexOf(".")+1)));

            redisTemplate.boundHashOps(KEY_WORKFLOW_ATTACHMENT).putIfAbsent(upRefId, resourceModel);
            Integer expire = MapUtils.getInteger(map, "expire", 1440);
            redisTemplate.expire(KEY_WORKFLOW_ATTACHMENT, expire, TimeUnit.MINUTES);
//            getBizObjectFacade().insertAttachments(Collections.singletonList(resourceModel));

            Map<String, Object> attachMap = new HashMap<>();
            attachMap.put("name",attachment.getName());
            attachMap.put("status",2);
            attachMap.put("size",length);
            attachMap.put("uid",upRefId);
            attachMap.put("mimeType",resourceModel.getMimeType());
            attachMap.put("response", MapUtil.of("data", JSON.parse(JSON.toJSONString(resourceModel))));

            return getOkResponseResult(attachMap,"成功");
        } catch (Exception e) {
            return getErrResponseResult(-1l,"系统异常");
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @GetMapping(value="testCover")
    public void testCover(String fileName, String color, Double left, Double top, Integer size, HttpServletResponse response){

        if (StringUtils.isEmpty(color)) {
            throw new RuntimeException("水印颜色不能为空");
        }
        if (left ==null || left.doubleValue()>=1 || left.doubleValue()<=0 ) {
            throw new RuntimeException(StrUtil.format("文字定位横坐标比不在区间(0,1)中,当前值={}", left));
        }
        if (top ==null || top.doubleValue()>=1 || top.doubleValue()<=0) {
            throw new RuntimeException(StrUtil.format("文字定位纵坐标比不在区间(0,1)中,当前值={}", top));
        }
        if (size ==null || size.intValue()>50 || size.intValue() <=10) {
            throw new RuntimeException(StrUtil.format("文字大小不在区间(10,50)中,当前值={}", size));
        }


        String courseName = "测试课程水印";
        InputStream inputStream = null;
        ByteArrayInputStream bais=null;
        try {
            inputStream = fileStoreFacade.downloadFile(fileName);
            if (inputStream==null){
                throw new RuntimeException(String.format("文件[%s]不存在", fileName));
            }

            byte[] bytes = CourseCoverWatermarkUtils.drawCourseInfoImg(inputStream, courseName,color,left,top,size);


            bais = new ByteArrayInputStream(bytes);


            response.reset();
            response.setDateHeader("Expires",0L);
            response.setHeader("Cache-Control","no-store, no-cache, must-revalidate");
            response.setHeader("Cache-Control","post-check=0, pre-check=0");
            response.setHeader("Pragma","no-cache");
            response.setContentType("image/png");
            OutputStream os = response.getOutputStream();
            os.write(bytes);
            os.flush();
            os.close();


        } catch (Exception e) {
            throw new RuntimeException(StrUtil.format("系统异常:{}",e.getMessage()));
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }


    /**
     * 刷新历史数据
     */
    @PostMapping("resetCourseCoverHistory")
    public ResponseResult resetCourseCoverHistory(@RequestBody Map<String,Object> map){

        List<String> bizIds = (List<String>) map.get("bizIds");


        BizObjectQueryModel query = new BizObjectQueryModel();
        query.setSchemaCode(SchemaUtils.courseCover);
        query.setQueryCode(SchemaUtils.courseCover_query);
        query.setPageable(new PageableImpl(0,30));

        Page<BizObjectModel> page = getBizObjectFacade().queryBizObjects(query);
        Map<String, Object> CoverTemp = page.getContent().stream().collect(Collectors.toMap(biz -> biz.getString("mbmc"), biz -> {
            List<Map<String, Object>> fm = (List<Map<String, Object>>) biz.getObject("fm");
            if (CollectionUtils.isNotEmpty(fm)) {

                Map<Object, Object> fmData = new HashMap<>();
                fmData.put("left", MapUtils.getDoubleValue(biz.getData(),"left"));
                fmData.put("top", MapUtils.getDoubleValue(biz.getData(),"top"));
                fmData.put("size", MapUtils.getInteger(biz.getData(),"size"));
                fmData.put("color", MapUtils.getString(biz.getData(),"color"));
                fmData.put("fm", fm.get(0));
                return fmData;
            }
            return null;
        }, (k1, k2) -> k1));


        List<String> failList = new ArrayList<>();

        bizIds.forEach(bizId ->{

            BizObjectCreatedModel bizObject = getBizObjectFacade().getBizObject(SchemaUtils.courseList, bizId);

            if (bizObject == null || bizObject.getData().isEmpty()) {
                failList.add(String.format("课程不存在biz=%s", bizId));
                return;
            }

            String category = bizObject.getString("category");

            if (StringUtils.isEmpty(category)) {
                failList.add(String.format("课程类型不能为空,bizId=%s", bizId));
                return;
            }

            Map<String,Object> fmData = (Map<String, Object>) CoverTemp.get(category);

            fmData.put("courseName",bizObject.getString("courseName"));

            if (MapUtils.isEmpty(fmData)) {
                failList.add(String.format("封面模板图片不存在,模板名称: %s", category));
                return;
            }

            ResponseResult result = courseCoverImagesWater(fmData);

            if (result.getErrcode() != 0) {
                failList.add(String.format("课程封面加水印失败 bizId: %s", bizId));
                log.info(String.format("课程封面加水印失败 bizId: %s , 失败信息:%s", bizId,result.getErrmsg()));
                return;
            }
            Map<String,Object> data = (Map<String, Object>) result.getData();



            Map<String, Object> model = (Map<String, Object>) ((Map<String, Object>) data.get("response")).get("data");
            model.put("deleted",false);

            BizObjectCreatedModel bizModel = new BizObjectCreatedModel(SchemaUtils.courseList, new HashMap<>(), false);
            bizModel.setId(bizObject.getId());
            bizModel.put("kcfm", Collections.singletonList(model));

            getBizObjectFacade().saveBizObject(getUserId(), bizModel, false);

        });


        if (failList.isEmpty()) {
            return getOkResponseResult("成功");
        }else {
            return getErrResponseResult(-1l, JSON.toJSONString(failList));
        }

    }

}
